﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Domain.Entities
{
    public class NetworkMaskV4
    {
        byte[] _networkMask = new byte[4];
        int _prefix;

        public int ValuePrefix
        {
            get
            {

                string bin = intToBinary(_networkMask[0]) +
                         intToBinary(_networkMask[1]) +
                         intToBinary(_networkMask[2]) +
                         intToBinary(_networkMask[3]);
                _prefix = (bin.Count(a => a == '1'));
                return _prefix;
            }
        }
        public byte[] ValueMask
        {
            get { return _networkMask; }
        }
        private NetworkMaskV4(byte[] networkMaskV4)
        {
            _networkMask = networkMaskV4;
        }
        public static NetworkMaskV4 Create(string arg)
        {
            NetworkMaskV4 networkMaskV4;
            if (TryParse(arg, out networkMaskV4))
            {
                return networkMaskV4;
            }
            else
            {
                return null;
            }
        }
        public static bool TryParse(string arg, out NetworkMaskV4 _networkMask)
        {
            IPAddressV4 ipV4tmp = IPAddressV4.Create(arg);
            if (ipV4tmp != null)
            {
                if (IsMaskValid(ipV4tmp.Value))
                {
                    _networkMask = new NetworkMaskV4(ipV4tmp.Value);
                    return true;
                }
            }
            _networkMask = null;
            return false;
        }
        static bool IsMaskValid(byte[] octets)
        {
            int[] validNums = { 0, 128, 192, 224, 240, 248, 252, 254, 255 };
            for (int i = 0; i < octets.Length; i++)
            {
                bool isValidNum = false;
                for (int j = 0; j < validNums.Length; j++)
                {
                    if (octets[i] == validNums[j])
                    {
                        isValidNum = true;
                        break;
                    }
                }
                if (!isValidNum)
                {
                    return false;
                }
            }
            string bin = intToBinary(octets[0]) +
                         intToBinary(octets[1]) +
                         intToBinary(octets[2]) +
                         intToBinary(octets[3]);
            string binPattern = @"(^1+0+$)|(^1+$)";
            if (Regex.IsMatch(bin, binPattern))
            {
                return true;
            }
            return false;
        }
        static string intToBinary(int oct)
        {
            string result = String.Empty;
            int rem;

            if (oct != 0)
            {
                while (oct > 0)
                {
                    rem = oct % 2;
                    oct = oct / 2;
                    result = rem.ToString() + result;
                }
                return result;
            }
            else
            {
                return "00000000";
            }
        }
        public override string ToString()
        {
            return String.Format("{0}.{1}.{2}.{3}", _networkMask[0], _networkMask[1], _networkMask[2], _networkMask[3]);
        }
    }
}
